#include<iostream>
#include<fstream>
#include<string>
#include<cstdlib>
#include<math.h>
#include<vector>
#include<queue>
using namespace std;

#define PI 3.14159265
#define vvint vector<vector<int> >
#define lon unsigned long long
#define forn(i,n) for(int (i)=0;(i)<(n);(i)++)
#define cola queue<pair<int,int> >
#define par pair<int,int>
#define HORIZONTAL -2
#define VERTICAL -3
#define OCUPADA -4
#define O(n) contador+=(n)

lon contador; //el contador de la cantidad de operaciones

/*void printt(vvint t,int n,int sano){
	forn(i,n){
		forn(j,n){
			cout << (t[i][j]==sano?'#':'.');
		}
		cout << endl;
	}
}*/

void printt(vvint t,int n,int sano){
	forn(i,n){
		forn(j,n){
			cout << (t[i][j]==sano?'#':'.');
		}
		cout << endl;
	}
}

//Calcula las combinaciones si el tablero esta todo sano
//productoria{j=1;m}{productoria{k=1;n}{4cos^2(pi*j/m+1)+4cos^2(pi*k/n+1)}}
lon todo_sano(int n,int m){
	//cout << "todo sano " << n << " " << m<< endl;
	int j = 1,k = 1;
	long double prod = 1;
	long double cos1;
	long double cos2;
	while(j <= m){
		k=1;
		while(k <= n){
			cos1 = cos((PI*j)/(m+1));
			cos2 = cos((PI*k)/(n+1));
			prod *= pow((4*cos1*cos1)+(4*cos2*cos2),0.25);
			k++;
			O(17);
		}
		j++;
		O(3);
	}
	O(5);
	return round(prod);
}

//Calcula las combinaciones cuando hay al menos una casilla rota (backtracking)
lon backtrack(vvint t, int n, int sano){
	//cout << "backtrack"<< endl;
	//printt(t,n,sano);
	lon cnt = 0; //lleva la cuenta de las combinaciones ya encontradas
	int pos = 0; //posicion en el tablero
	int dir = 1; //direccion en la que me estoy moviendo (1=hacia adelante y -1=hacia atras)
	while(pos>=0){
		if(pos==n*n){//se termino el tablero
			cnt++;//sumo una solución
			pos--;//vuelvo una posición
			dir = -1;//empiezo a ir para atras para cambiar algunas fichas de lugar y encontrar nuevas soluciones
			O(6);
		}
		
		int i = pos/n; //fila en la que estoy segun la posición
		int j = pos%n; //columna en la estoy segun la posición
		if(dir==1){ //si estoy yendo hacia adelante
			if(t[i][j]==sano){ //si esta posición esta sana
				if(i<n-1 && t[i+1][j]==sano){//si puedo poner una ficha verticalmente
					t[i][j] = VERTICAL; //pongo la ficha
					t[i+1][j] = OCUPADA; //marco la posicion de abajo como ocupada
					O(6);
				}else if(j<n-1 && t[i][j+1]==sano){//si puedo poner una ficha horizontalmente
					t[i][j] = HORIZONTAL;//pongo la ficha
					t[i][j+1] = OCUPADA;//marco la posición de al lado como ocupada
					pos++;//aumento el pos porque la siguiente ya esta ocupada
					i = pos/n;//actualizo "i" segun la nueva posición
					j = pos%n;//actualizo "j" segun la nueva posición
					O(13);
				}else{
					dir = -1;//como no pude poner la ficha vertical ni horizontal se que por ese camino ya no hay solución entonces empiezo a ir para atras
					O(7);
				}
			}
		}else{//si estoy yendo hacia atras
			if(t[i][j]==VERTICAL){//si me encuentro con una ficha puesta verticalmente
				if(j<n-1 && t[i][j+1]==sano){//si al sacar la ficha vertical puedo poner una horizontal
					t[i+1][j] = sano;//desocupo esta posición
					t[i][j] = HORIZONTAL;//pongo la ficha horizontal
					t[i][j+1] = OCUPADA;//marco la posición de al lado como ocupada
					dir = 1;//empiezo a ir para adelante buscando nuevas combinaciones
					O(8);
				}else{
					t[i][j]=sano;//desocupo esta posición
					t[i+1][j]=sano;//desocupo esta posición
					O(6);
				}			
			}else if(t[i][j]==HORIZONTAL){//si me encuentro con una ficha puesta horizontalmente
				t[i][j]=sano;//desocupo esta posición
				t[i][j+1]=sano;//desocupo esta posición
				O(5);
			}
		}
		pos+=dir;//me muevo una posición en el sentido de la dirección
		O(3);
	}
	O(4);
	return cnt;
}

lon contar(vvint& t, int n, int sano){
	bool todosano=true;
	int minx=-1,miny=-1,maxx=-1,maxy=-1;
	O(5);
	forn(i,n) forn(j,n){
		if(t[i][j]==sano){
			if(minx==-1){minx=j;miny=i; O(3);}
			if(maxy>=0 && i>=maxy){todosano=false; O(3);}
			if(maxx<j){
				if(miny==i){maxx=j; O(3);}
				else{todosano=false; O(3);} 
			}
			if(minx>j){
				todosano=false; O(1);
			}
			
		}else{
			if(minx==j && maxy<0){maxy=i; O(3);}
			else if(maxy<0 && minx<j && j<=maxx){todosano=false; O(4);} 
			O(2);
		}
	}
	if(todosano) return todo_sano((maxy<0?n:maxy)-miny,maxx-minx+1);
	return backtrack(t,n,sano);
}

bool bfs(vvint& t, int n, int i, int j, int num){
	int v1[4]={1,-1,0,0};
	int v2[4]={0,0,1,-1};
	int casillasBlancasSanas = 0;
	int casillasNegrasSanas = 0;
	cola q;
	q.push(par(i,j));
	t[i][j]=num;
	if(i%2==j%2){casillasBlancasSanas++;O(4);}
	else{casillasNegrasSanas++;O(4);}
	while(!q.empty()){
		par elem=q.front(); q.pop();
		O(3);
		forn(d,4){
			int vi=elem.first+v1[d];
			int vj=elem.second+v2[d];
			O(6);
			if(vi>=0 && vi<n && vj>=0 && vj<n && t[vi][vj]==0){
				t[vi][vj]=num;
				q.push(par(vi,vj));
				O(7);
				if(vi%2==vj%2){casillasBlancasSanas++;O(3);}
				else{casillasNegrasSanas++;O(3);}
			}
		}
	}
	O(8);
	return casillasBlancasSanas==casillasNegrasSanas;
}

lon combinaciones(vvint& t, int n, int casillasBlancasSanas, int casillasNegrasSanas){
	if(casillasBlancasSanas!=casillasNegrasSanas || casillasBlancasSanas==0){O(3); return 0;}
	else if(2*casillasBlancasSanas==n*n){O(5); return todo_sano(n,n);}
	else{
		int sub=1;
		forn(i, n) forn(j,n){
			if(t[i][j]==0){
				if(!bfs(t,n,i,j,sub)){O(2); return 0;}
				sub++;
				O(2);
			}
		}
		lon total=1;
		//printta(t,n);
		for(int i=1;i<sub;i++){
			//printt(t,n,i);
			lon c=contar(t,n,i);
			if(c==0){O(4); return 0;}
			else total*=c;
			O(6);
		}
		O(6);
		return total;
	}
}

int main(int argc,char** argv){
	clock_t start,end;
	while(true){
		int n;
		cin >> n; //Guarda en n el tamaño de la matriz
		if(n==-1)break;
		vvint t (n,vector<int>(n,0));
		//ARMA UN TABLERO
		char buff;
		int casillasBlancasSanas = 0;
		int casillasNegrasSanas = 0;
		forn(i,n) forn(j,n){
			cin >> buff;
			t[i][j] = buff=='#'?0:-1;
			if(t[i][j]==0){
				if(i%2==j%2){casillasBlancasSanas++;}
				else{casillasNegrasSanas++;}
			}
		}
		if(argc>1 && string(argv[1])=="time"){ //si el primer argumento es "time" mido tiempos..
			float secs = argc>2?atof(argv[2]):0.5; //lo ejecuto hasta que tarde al menos secs segundos, para tener presicion (0.5 por default)
			int tries = argc>3?atoi(argv[3]):1; // tomo el tiempo times veces por dato de entrada, para disminuir el error
			forn(tr,tries){
				start = clock(); //guardo el tiempo
				lon cont=0;
				while((double)(clock()-start)/CLOCKS_PER_SEC<secs){ //evaluo la funcion hasta que tarde al menos secs
					vvint t2=t;
					combinaciones(t2,n,casillasBlancasSanas,casillasNegrasSanas);
					cont++;
				}
				end = clock(); //guardo el tiempo de finalizacion
				double tiempo=(double)(end-start)/(CLOCKS_PER_SEC*cont); //el tiempo total de evaluacion es lo_que_tardo/cantidad_de_veces_que_lo_llamo
				printf("%.8f ",tiempo); //imprimo el resultado con 8 decimales de presicion
			}
			cout << endl;
			
		}else if(argc>1 && string(argv[1])=="count"){ // si el argumento es "count", cuento cantidad de operaciones..
			contador=0;
			combinaciones(t, n,casillasBlancasSanas, casillasNegrasSanas);
			cout << contador << endl; //imprimo la cuenta
			
		}else{ //si no me pasan argumentos devuelvo el resultado
			cout << combinaciones(t, n,casillasBlancasSanas, casillasNegrasSanas) << endl;
		}
	}
	return 0;
}
